package com.dzk.cp.c11x5.catcher.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import net.sf.json.JSONArray;
import net.sf.json.JsonConfig;
import net.sf.json.util.PropertyFilter;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;

import com.dzk.cp.c11x5.catcher.CodeCatcherService;
import com.dzk.cp.c11x5.dao.R5Dao;
import com.dzk.cp.c11x5.pojo.R5;
import com.dzk.cp.c11x5.util.C11x5Utils;
import com.dzk.cp.c11x5.vo.C11x5CodeJsonVO;
import com.dzk.cp.util.CpUtils;
import com.dzk.cp.util.HttpUtils;

public abstract class CodeCatcherServiceImpl<T extends R5> implements CodeCatcherService<T> {
	
	private static final Logger log = Logger.getLogger(CodeCatcherServiceImpl.class);
	
	@Override
	public void catchCodeByDate(String date) {
		Map<String, String> codeMap = this.getCodesByDate(this.getByDateURL(date), null);
		for (String issue : codeMap.keySet()) {
			T r5 = this.createR5(issue, codeMap.get(issue), this.getEntityClass());
			this.getR5Dao().save(r5);
		}
	}
	
	@Override
	public void catchCodeByIssue(String issues) {
		C11x5CodeJsonVO[] codeJsonVOs = this.getCodesByIssue(this.getByIssueURL(issues), null);
		for (C11x5CodeJsonVO codeJsonVO : codeJsonVOs) {
			if (StringUtils.isNotEmpty(codeJsonVO.getCode())) {
				T r5 = this.createR5(codeJsonVO.getIssue(), codeJsonVO.getCode(), this.getEntityClass());
				this.getR5Dao().save(r5);
			}
		}
	}
	
	protected abstract Class<T> getEntityClass();
	
	protected abstract R5Dao<T> getR5Dao();
	
	protected abstract String getByDateURL(Object... params);
	
	protected abstract String getByIssueURL(Object... params);
	
	protected Map<String, String> getCodesByDate(String url, Map<String, String> params) {
		String result = HttpUtils.requestGBK(url, params);
		return parseHtml(result);
	}
	
	protected Map<String, String> parseHtml(String html) {
		Map<String, String> codeMap = new TreeMap<String, String>();
		html = html.replaceAll("\t|\r|\n", "").replaceAll(">\\s+<", "><");
		int beginIndex = html.indexOf("<table") + 63 + 4;
		int endIndex = html.indexOf("</table>") - 5;
		String str1 = html.substring(beginIndex, endIndex);
		String[] trs = str1.split("</tr><tr>");
		for (int i = 1; i < trs.length; i++) {
			String str2 = trs[i].substring(4, trs[i].length() - 5);
			String[] tds = str2.split("</td><td>");
			String str3 = tds[1].substring(41, tds[1].length() - 13);
			String[] spans = str3.split("</span><span class=\"redball\">");
			String code = "";
			for (String span : spans) {
				code += span + " ";
			}
			codeMap.put(tds[0], code.trim());
		}
		return codeMap;
	}
	
	protected C11x5CodeJsonVO[] getCodesByIssue(String url, Map<String, String> params) {
		String result = HttpUtils.requestGBK(url, params);
		JsonConfig jsonConfig = new JsonConfig();
		jsonConfig.setJsonPropertyFilter(new PropertyFilter() {
			@Override
			public boolean apply(Object o, String n, Object v) {
				return !n.equals("code") && !n.equals("issue");
			}
		});
		JSONArray jsonArray = JSONArray.fromObject(result, jsonConfig);
		C11x5CodeJsonVO[] codeJsonVOs = (C11x5CodeJsonVO[]) JSONArray.toArray(jsonArray, C11x5CodeJsonVO.class);
		return codeJsonVOs;
	}
	
	protected T createR5(String issue, String code, Class<T> clazz) {
		log.info(clazz.getSimpleName() + ":{issue: " + issue + ", code: " + code + "}");
		T r5 = null;
		try {
			r5 = clazz.newInstance();
			r5.setQs(issue);
			String[] noArr = code.split(" ");
			List<Integer> nos = new ArrayList<Integer>();
			for (int i = 0; i < 5; i++) {
				nos.add(Integer.valueOf(noArr[i]));
			}
			r5.setN1(nos.get(0));
			r5.setN2(nos.get(1));
			r5.setN3(nos.get(2));
			r5.setN4(nos.get(3));
			r5.setN5(nos.get(4));
			Collections.sort(nos);
			String codeStr = "";
			for (Integer cd : nos) {
				codeStr += CpUtils.fore2zero(cd) + " ";
			}
			codeStr = codeStr.trim();
			r5.setNs(codeStr);
			r5.setJs(C11x5Utils.getOddNum(nos));
			r5.setOs(C11x5Utils.getEvenNum(nos));
			r5.setDs(C11x5Utils.getBigNum(nos));
			r5.setXs(C11x5Utils.getSmallNum(nos));
			r5.setY0(C11x5Utils.getY0Num(nos));
			r5.setY1(C11x5Utils.getY1Num(nos));
			r5.setY2(C11x5Utils.getY2Num(nos));
			r5.setLx(C11x5Utils.getLX(nos));
			r5.setHz(C11x5Utils.getSum(nos));
			r5.setKd(C11x5Utils.getKd(nos));
			r5.setYl(this.getR5Dao().getCurrentYl(codeStr));
			r5.setCm(this.getCm(nos));
		} catch (Exception e) {
			e.printStackTrace();
		}
		return r5;
	}
	
	private int getCm(List<Integer> nos) {
		int n = 0;
		T lastR5 = this.getR5Dao().getLastR5();
		if (lastR5 != null) {
			List<Integer> lastNos = new ArrayList<Integer>();
			lastNos.add(lastR5.getN1());
			lastNos.add(lastR5.getN2());
			lastNos.add(lastR5.getN3());
			lastNos.add(lastR5.getN4());
			lastNos.add(lastR5.getN5());
			n = C11x5Utils.getCM(nos, lastNos);
		}
		return n;
	}

}
